/**
 * 少用全局变量，所有需要全局变量的都由core模块封装在提供出去。
 */
define([
    "jQuery",
    "validator",
    'tools',
    "bootstrapNotify"
], function (jQuery, validator, tools, notify) {
    var core = {};

    // 用moment代替
    // 对Date的扩展，将 Date 转化为指定格式的String   
    // 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符，   
    // 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字)   
    // 例子：   
    // (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423   
    // (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18   
    // Date.prototype.format = function (fmt) { //author: meizz
    //     var o = {
    //         "M+": this.getMonth() + 1,                 //月份
    //         "d+": this.getDate(),                    //日
    //         "h+": this.getHours(),                   //小时
    //         "m+": this.getMinutes(),                 //分
    //         "s+": this.getSeconds(),                 //秒
    //         "q+": Math.floor((this.getMonth() + 3) / 3), //季度
    //         "S": this.getMilliseconds()             //毫秒
    //     };
    //     if (/(y+)/.test(fmt))
    //         fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    //     for (var k in o)
    //         if (new RegExp("(" + k + ")").test(fmt))
    //             fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    //     return fmt;
    // };

    core._showLoading = true;
    core.enableShowLoading = function (option) {
        if (option === undefined) core._showLoading = true;
        if (typeof option === 'boolean' && option === false) core._showLoading = false;
    };
    function initSystem() {
        $(function () {
            var notifier;
            $(document).ajaxStart(function () {
                if (notifier != undefined) notifier.close();
                if (core._showLoading) notifier = tools.loading();
            }).ajaxStop(function () {
                if (notifier != undefined) notifier.close();
            });
        });
    }

    initSystem();

    /**
     * Global data get or set.If param of data is null return data,else set data.
     * @param name data name.
     * @param data new data.
     * @returns {*|jQuery}
     */
    function globalData(name, data) {
        if (data) {
            $("#console-config").data(name, data);
        } else {
            return $("#console-config").data(name);
        }
    }

    core.globalData = globalData;

    function clearTimer() {
        context.intervals.forEach(function (id) {
            clearInterval(id);
        });
        context.intervals = [];
        context.timeouts.forEach(function (id) {
            clearTimeout(id);
        });
        context.timeouts = [];
    }

    core.clearTimer = clearTimer;

    function _setInterval(f, t) {
        context.intervals.push(setInterval(f, t));
    }

    core.setInterval = _setInterval;

    function setTimeout(f, t) {
        context.timeouts.push(setTimeout(f, t));
    }

    core.setTimeout = setTimeout;

    function getUrl(url) {
        return context.path + url;
    }

    core.getUrl = getUrl;

    function getSelector(selector) {
        console.log("type of " + typeof selector);
        if (typeof selector !== "string") {
            //selector = selector.selector;
            return selector;
        }

        return $(selector);
    }

    core.getSelector = getSelector;

    function autoHeight(selector) {
        function _autoHeight() {
            // console.log("$(window).height() - 80 = " + ($(window).height() - 80));
            getSelector(selector).height($(window).height() - 80);
        }

        $(window).resize(function () {
            _autoHeight();
        }).resize();
    }

    core.autoHeight = autoHeight;

    function setWidth(selector, refSelector, median) {
        function _setWidth() {
            if (median == null) median = 600;

            var ref = getSelector(refSelector);
            getSelector(selector).width(ref.width() < median ? ref.width() : median);
        }

        $(window).resize(function () {
            _setWidth()
        }).resize();

        _setWidth();
    }

    core.setWidth = setWidth;

    function setHeight(selector, refSelector, median) {
        if (median == null) median = 400;

        var ref = getSelector(refSelector);
        getSelector(selector).height(ref.height() > median ? ref.height() : median);
    }

    core.setHeight = setHeight;

    function showPostForm(selector, options, callback) {
        if (typeof selector != "string") {
            // selector is null.
            callback = options;
            options = selector;
            selector = "#modal";
        }
        selector = $(selector);

        //自定义表单title
        var formTitle = options.formTitle;
        var modalTitle = "表单";
        if (!isEmpty(formTitle)) {
            modalTitle = formTitle.toString();
        }
        $.ajax(
            {
                url: options.formUrl.toString(),
                type: "post",
                data: options.data,
                dataType: "html",
                success: function (data) {
                    var form = selector.find("form");
                    selector.find(".modal-title").html(modalTitle);
                    selector.find(".modal-body").html("");
                    selector.find(".modal-body").html(data);

                    var saveBtn = selector.find(".btn-save");
                    //自定义表单保存按钮内容
                    var saveBtnContent = options.saveBtnContent;
                    if (!isEmpty(saveBtnContent)) {
                        saveBtn.html(saveBtnContent.toString());
                    }
                    if (!options.postUrl) {
                        saveBtn.hide();
                        selector.find(".edit-action").hide();
                        disabled(form);
                    } else {
                        saveBtn.show();
                        saveBtn.unbind("click");
                        saveBtn.on("click", function (e) {
                            validator(form, function () {
                                $.ajax({
                                    url: options.postUrl,
                                    type: "post",
                                    data: $(form.selector).serialize(),
                                    dataType: "json",
                                    success: function (msg) {
                                        if (message(msg)) {
                                            if (!isEmpty(options.successUrl)) {
                                                loadContent(options.successUrl);
                                            }
                                        }

                                        callback && callback(msg);
                                    }
                                });
                            });
                        })
                    }

                    selector.modal();
                }
            }
        );
    }

    core.showPostForm = showPostForm;

    function findModalTitle(options) {
        //自定义表单title
        var formTitle = options.formTitle;
        var modalTitle = "表单";
        if (!isEmpty(formTitle)) {
            modalTitle = formTitle.toString();
        }

        return modalTitle;
    }

    // 待完。先继续用jQuery2的showForm方法。
    function showModalForm(options, callback) {
        var modalTitle = findModalTitle(options);
        $.ajax(
            {
                url: options.formUrl.toString(),
                type: "get",
                dataType: "html",
                success: function (data) {
                    var $el = $(selector);
                    var modal = tools.modalSave({
                        title: modalTitle
                    });
                    modal.getModalBody().html(data);
                    modal.getModalBody().find('form');
                    // var $form = $('#recordForm');//$el.find("form:first");
                    // $el.find(".modal-title").html(modalTitle);
                    // $el.find(".modal-body").html("");
                    // $el.find(".modal-body").html(data);

                    // var saveBtn = $el.find(".btn-save");
                    // //自定义表单保存按钮内容
                    // var saveBtnContent = options.saveBtnContent;
                    // if (!isEmpty(saveBtnContent)) {
                    //     saveBtn.html(saveBtnContent.toString());
                    // }
                    // if (!options.postUrl) {
                    //     saveBtn.hide();
                    //     $el.find(".edit-action").hide();
                    //     disabled($form);
                    // } else {
                    //     saveBtn.show();
                    //     saveBtn.unbind("click");
                    //     saveBtn.on("click", function (e) {
                    //         validator($form, function () {
                    //             console.log($form.serialize());
                    //             console.log($form.attr('name'));
                    //             console.log(selector);
                    //             console.log($el);
                    //             $.ajax({
                    //                 url: options.postUrl,
                    //                 type: "post",
                    //                 data: $form.serialize(),
                    //                 dataType: "json",
                    //                 success: function (msg) {
                    //                     if (isSuccess(msg)) {
                    //                         $(".modal").modal("hide");
                    //                         noticeMessage(msg.info);
                    //                         if (!isEmpty(options.successUrl)) {
                    //                             loadContent(options.successUrl);
                    //                         }
                    //                     } else {
                    //                         showMessage(msg.info);
                    //                     }
                    //
                    //                     callback && callback(msg);
                    //                 }
                    //             });
                    //         });
                    //     })
                    // }

                    // $el.modal();
                }
            }
        );
    }

    core.showModalForm = showModalForm;

    /**
     * Show form with modal.
     * @param selector
     * @param options {
      formUrl:form page url,
      postUrl:post form url,
      successUrl:success url,
      title: modal title,
      }
     * @param callback
     */
    function showForm(selector, options, callback) {
        if (typeof selector != "string") {
            // selector is null.
            callback = options;
            options = selector;
            selector = "#modal";
        }

        var $el = getSelector(selector);

        var modalTitle = findModalTitle(options);
        $.ajax(
            {
                url: options.formUrl.toString(),
                type: "get",
                dataType: "html",
                success: function (data) {
                    // var $form = $el.find('form');
                    $el.find(".modal-title").html(modalTitle);
                    $el.find(".modal-body").html("");
                    $el.find(".modal-body").html(data);

                    var saveBtn = $el.find(".btn-save");
                    //自定义表单保存按钮内容
                    var saveBtnContent = options.saveBtnContent;
                    if (!isEmpty(saveBtnContent)) {
                        saveBtn.html(saveBtnContent.toString());
                    }
                    if (!options.postUrl) {
                        saveBtn.hide();
                        $el.find(".edit-action").hide();
                        disabled($el.find('form'));
                    } else {
                        saveBtn.show();
                        saveBtn.unbind("click");
                        saveBtn.on("click", function () {
                            validator($el.find('form'), function () {
                                var formData = new FormData($el.find('form')[0]);
                                $.ajax({
                                    url: options.postUrl,
                                    type: "post",
                                    data: formData,
                                    processData: false,
                                    contentType: false,
                                    dataType: "json",
                                    success: function (msg) {
                                        if (isSuccess(msg)) {
                                            $(".modal").modal("hide");
                                            noticeMessage(msg.info);
                                            if (!isEmpty(options.successUrl)) {
                                                loadContent(options.successUrl, function (data) {
                                                    var scope = globalData("scope");
                                                    clearTimer();
                                                    if (scope) {
                                                        scope.$destroy && scope.$destroy();
                                                    }

                                                    var $injector = angular.injector(['ng']);
                                                    $injector.invoke(function ($compile, $rootScope, $sce) {
                                                        scope = $rootScope.$new();
                                                        scope.$sce = $sce;
                                                        $compile($("div .main")[0])(scope);
                                                        scope.$apply();
                                                        core.globalData("scope", scope);
                                                    });
                                                    return data;
                                                });
                                            }
                                        } else {
                                            showMessage(msg.info);
                                        }

                                        callback && callback(msg);
                                    }
                                });
                            });
                        })
                    }

                    $el.modal();
                }
            }
        );
    }

    core.showForm = showForm;

    function showApplyForm(selector, options, callback) {
        if (typeof selector != "string") {
            // selector is null.
            callback = options;
            options = selector;
            selector = "#modal";
        }
        var $el = $(selector);
        var modalTitle = findModalTitle(options);
        $.ajax(
            {
                url: options.formUrl.toString(),
                type: "get",
                dataType: "html",
                success: function (data) {
                    $el.find(".modal-title").html(modalTitle);
                    $el.find(".modal-body").html("");
                    $el.find(".modal-body").html(data);

                    var applyBtn = $el.find(".btn-allow");
                    var rejectBtn = $el.find(".btn-reject");
                    var revocationBtn = $el.find(".btn-revocation");
                    addApplyAction(applyBtn, options, selector, "allow", callback);
                    addApplyAction(rejectBtn, options, selector, "reject", callback);
                    addApplyAction(revocationBtn, options, selector, "revocation", callback);
                    $el.modal();
                }
            }
        );
    }

    core.showApplyForm = showApplyForm;

    function isEmpty(v) {
        return tools.isEmpty(v);
    }

    core.isEmpty = isEmpty;

    function addApplyAction(btn, options, selector, type, callback) {
        if (!options.postUrl) {
            btn.hide();
            disabled($(selector).find('form'));
        } else {
            btn.show();
            btn.unbind("click");
            btn.on("click", function () {
                validator($(selector).find('form'), function () {
                    console.log("options.successUrl222:"+options.successUrl);
                    $.ajax({
                        url: options.postUrl + "/" + type,
                        type: "post",
                        data: $(selector).find('form').serialize(),
                        dataType: "json",
                        success: function (msg) {
                            console.log("options.33333:"+options.successUrl);
                            if (!isEmpty(options.successUrl)) {
                                if (message(msg)) {
                                    loadContent(options.successUrl);
                                }
                            }
                            return callback && callback(msg);
                        }
                    });
                });
            })
        }
    }

    /*
     *  Init form's elements by element's name.
     */
    function resetForm(formSelector, data) {
        $.each($(formSelector + " input"), function () {
            var node = $(this);
            var name = node.attr("name");
            if (name && data && data[name]) {
                node.val(data[name]);
            } else {
                node.val("");
            }
        });

    }

    core.resetForm = resetForm;

    function isSuccess(message) {
        return message.code == 200;
    }

    core.isSuccess = isSuccess;

    function noticeMessage(message) {
        $.notify({
            icon: 'glyphicon glyphicon-ok-sign',
            // title: "操作结果:",
            message: message
        }, {
            delay: 5,
            type: "success",
            placement: {
                from: "top",
                align: "center"
            },
            offset: 5
        });
    }

    core.noticeMessage = noticeMessage;
    /*
     *  Return true when message code is 200,otherwise return false.
     */
    function message(message) {
        if (message.code == 200) {
            $(".modal").modal("hide");
            $("#messageModalBody").html(message.info);
            $("#messageModal").modal();
            return true;
        } else {
            $("#messageModalBody").html(message.info);
            $("#messageModal").modal();
            return false;
        }
    }

    core.message = message;

    /*
     *  Show message modal.
     */
    function showMessage(message, options) {
        var defaultOptions = {title: "消息"};
        defaultOptions = $.extend({}, defaultOptions, options);
        defaultOptions.title && $("#messageModalTitle").html(defaultOptions.title);
        $("#messageModalBody").html(message);
        $("#messageModal").modal();
    }

    core.showMessage = showMessage;

    /**
     * Disabled all input,select and textarea's elements.
     * @param {string} selector
     */
    function disabled(selector) {
        getSelector(selector).find("input,select,textarea").each(function () {
            $(this).attr("disabled", true);
        })
    }

    core.disabled = disabled;

    /**
     * Validate
     * @param {string} selector
     * @param {object} options
     */
    function addValidator(selector, options) {
        getSelector(selector).validator(options);
    }

    core.addValidator = addValidator;

    /**
     * Validate
     * @param {string} selector
     * @param {function} callback
     */
    function validator(selector, callback) {
        var $el = getSelector(selector);
        $el.validator('update');
        $el.validator('validate');

        var $error = $el.find(".has-error:first");// form .has-error:first

        if ($error.length == 0) {
            callback && callback();
        } else {
            // $error.find("input,select").focus();
            console.log("Validator find error is [" + $error.text() + "]");
        }
    }

    core.validator = validator;

    function prepareContentHeader(title) {
        var html = '<h1>' + title + '</h1>';
        html += '<ol class="breadcrumb">';
        html += '<li><a href="./"><i class="fa fa-dashboard"></i>首页</a></li>';
        html += '<li class="active">' + title + '</li>';
        html += '</ol>';
        return html;
    }

    function loadHtml(targetSelector, url, data, callback) {
        $.ajax({
            url: url,
            data: data,
            success: function (contentHtml) {
                getSelector(targetSelector).html(contentHtml);
                callback && callback(contentHtml);
            }
        })
    }

    core.loadHtml = loadHtml;

    /**
     * Ajax html.Then replace content and content-header.At last call callback fn.
     * @param url request content's html.
     * @param headerHtml header html
     * @param callback at last call.
     */
    var currentUrl = null;

    function loadContent(url, headerHtml, callback) {
        if (typeof headerHtml == "function") {
            callback = headerHtml;
            headerHtml = undefined;
        }
        currentUrl = url;
        $.ajax({
            url: url,
            success: function (contentHtml) {
                if (url != currentUrl) {
                    return;
                }
                htmlContent(contentHtml, headerHtml);
                callback && callback(contentHtml);
            }
        })
    }

    core.loadContent = loadContent;

    core.loadContentWithAngular = function (url) {
        loadContent(url, function (data) {
            var scope = globalData("scope");
            clearTimer();
            if (scope) {
                scope.$destroy && scope.$destroy();
            }

            var $injector = angular.injector(['ng']);
            $injector.invoke(function ($compile, $rootScope, $sce) {
                scope = $rootScope.$new();
                scope.$sce = $sce;
                $compile($("div .main")[0])(scope);
                scope.$apply();
                core.globalData("scope", scope);
            });
            return data;
        });
    }

    function initDVLink() {
        $(".dv").click(function () {
            jumpToTree($(this).attr("targetId"));
            return false;
        })
    }

    core.initDVLink = initDVLink;

    function jumpToTree(id) {
        var treeObj = $.fn.zTree.getZTreeObj("menuTree");
        var node = treeObj.getNodesByParam("id", id)[0];
        var parent = node.getParentNode();
        while (parent) {
            treeObj.expandNode(parent, true, false, true);
            parent = parent.getParentNode();
        }
        treeObj.selectNode(node, false, false);
        treeObj.setting.callback.onClick(null, null, node)
    }

    core.jumpToTree = jumpToTree;

    /**
     * Replace content and content-header to new html.
     * @param contentHtml new content html.
     * @param headerHtml new header html.
     */
    function htmlContent(contentHtml, headerHtml) {
        headerHtml && $(".content-header").html(headerHtml);
        $(".content").html("");
        $(".content").html(contentHtml);
        initDVLink();
        $(".mCustomScrollbar").mCustomScrollbar({
            scrollbarPosition: "inside",
            scrollInertia: 100,
            theme: "minimal-dark"
        });
    }

    core.htmlContent = htmlContent;

    /**
     * Add onclick event for ajax html with url.Then replace content's html.
     *
     * @param selector who add event.
     * @param callback after replace content call.
     */
    function linkOnclick(selector, callback) {
        $(selector).on("click", function (e) {
            var elem = $(this);
            var url = elem.data("url");
            if (!url) {
                url = elem.attr("href");
                elem.data("url", url);
                elem.attr("href", "#");
            }
            loadContent(url, prepareContentHeader(e.target.innerText), callback);
        })
    }

    core.linkOnclick = linkOnclick;

    /**
     * demo elements <a class="nav-link" data-code="audit_log_list" data-options='{"parentCode":"common_manage"}'></a>
     * no use
     * @param selector
     * @param baseUrl
     */
    function codeLinkOnclick(selector, baseUrl) {
        !selector && (selector = ".nav-link");
        !baseUrl && (baseUrl = "/base/permission");

        var urls = new core.Urls(getUrl(baseUrl));
        $(selector).each(function () {
            var elem = $(this);
            var code = elem.data("code");
            var options = elem.data("options");
            var data = $.extend({}, options, {code: code});
            $.ajax({
                url: urls.findFirst(),
                data: data,
                dataType: "json",
                success: function (data) {
                    elem.attr("href", data.pageUrl);
                    elem.attr("title", data.name);
                    elem.attr("title2", data.name);
                    linkOnclick(selector);
                }
            });
        });
    }

    core.codeLinkOnclick = codeLinkOnclick;

    /*
     *  Prepare url list for common module with base url.
     */
    function Urls(baseUrl) {
        this._baseUrl = baseUrl;

        this.list = function () {
            return getUrl(this._baseUrl + "/list");
        };
        this.new = function () {
            return getUrl(this._baseUrl + "/form");
        };
        this.view = function (id) {
            return getUrl(this._baseUrl + "/form/view/" + id);
        };
        this.viewByAttr = function (id, attr) {
            return getUrl(this._baseUrl + "/form/view/" + id + "/" + attr);
        };
        this.edit = function (id) {
            return getUrl(this._baseUrl + "/form/edit/" + id);
        };
        this.editByAttr = function (id, attr) {
            return getUrl(this._baseUrl + "/form/edit/" + id + "/" + attr);
        };
        this.findFirst = function () {
            return getUrl(this._baseUrl + "/rest/findFirst");
        };
        this.save = function () {
            return getUrl(this._baseUrl + "/rest/save");
        };
        this.insert = function () {
            return getUrl(this._baseUrl + "/rest/insert");
        };
        this.update = function () {
            return getUrl(this._baseUrl + "/rest/update");
        };
        this.delete = function (id) {
            return getUrl(this._baseUrl + "/rest/delete/" + id);
        };
        this.export = function () {
            return getUrl(this._baseUrl + "/export/xls");
        };
        this.exportXls = function () {
            return getUrl(this._baseUrl + "/export/xls");
        };
        this.tree = function () {
            return getUrl(this._baseUrl + "/rest/tree/");
        };
        this.selectedTree = function () {
            return getUrl(this._baseUrl + "/rest/tree/");
        };
        this.custom = function (remainingUrl) {
            return getUrl(this._baseUrl + remainingUrl);
        };
    }

    core.Urls = Urls;


    return core;
});